from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field
import os
from dotenv import load_dotenv
load_dotenv()

# 1. 定义 Pydantic 模型，作用：相当于给模型一个 “任务清单”，明确告诉它需要输出哪些信息，以及每个信息的格式。
class ProductInfo(BaseModel):
    product_name: str = Field(description="商品名称，需准确提取文本中的商品全称")
    price: str = Field(description="商品价格，仅保留数字和货币符号（如 99元、$19.99）")
    in_stock: str = Field(description="是否有货，仅输出 yes 或 no")

# 2. 初始化解析器，作用是将模型输出的文本转换为 JSON 格式（字典）
parser = JsonOutputParser(
    pydantic_object=ProductInfo,
)
print('parser.get_format_instructions(),',parser.get_format_instructions())
# 3. 构建提示词模板
prompt = ChatPromptTemplate(
    messages=[
        ("system", "请解析商品描述，按格式输出：\n{format_instructions}\n仅输出JSON，不要额外内容。"),
        ("user", "商品描述：{product_desc}")
    ],
    input_variables=["product_desc"],# 声明模板中需要替换的变量
    partial_variables={"format_instructions": parser.get_format_instructions()} # 显式声明固定变量
)

# 4. 初始化模型
model = init_chat_model(
    model="Qwen/Qwen3-8B",
    model_provider="openai",
    base_url="https://api.siliconflow.cn/v1/",
    api_key=os.environ.get('OPENAI_API_KEY'),
)

# 5. 执行链
chain = prompt | model | parser
result_dict = chain.invoke({
    "product_desc": "小米Redmi Note 13 Pro 5G手机，8GB+256GB版本售价1799元，目前库存充足。"
})

# 手动将字典转换为 Pydantic 模型
result = ProductInfo.model_validate(result_dict)

print(result)  # 输出 Pydantic 模型对象
print(result.product_name)  # 现在可以直接访问字段了

print(result_dict.get("product_name"))